package com.webserver.core;

import com.webserver.http.HttpServletRequest;
import com.webserver.http.HttpServletResponse;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;

/**
 * 处理请求的环节
 */
public class DispatcherServlet {
    //加载类的时候,只需要new一次static目录对象,无需多次创建,节省空间
    private static File staticDir;

    static {//属于类,随着类的加载自动加载,并且只会存在一份
        /*
         * 实际开发中,我们常用的相对路径都是类的加载路径,对应的写法:
         * 类名.class.getClassLoader().getResource("./")
         * 这里的"./"就是当前目录指定类加载路径的开始目录,实际位置就是JVM立即的当前类的包名中的最上一层目录.
         * 例如下面的代码:
         * 当前类ClientHandler的包是:com.webserver.core
         * 那么包的最上级就是com.因此类加载路径的最开始就是com的最上级目录
         * 实际就是项目的target/classes目录了
         * maven项目编译后会将src/main/java目录和src/main/resources目录最终合并到target/classes目录下
         */
        /*
         * File(File parent,String sub)
         * 从父级目录下,定位子集目录sub
         */
        try {
            staticDir = new File(
                    ClientHandler.class.getClassLoader().getResource(
                            "./static"
                    ).toURI()
            );
        } catch (URISyntaxException e) {//静态代码块中有异常只能自己处理
            e.printStackTrace();
        }
    }

    public void service(HttpServletRequest request, HttpServletResponse response) {
        /*
         * 如果浏览器输入的是http://localhost:8088/myweb/index.html
         * 则抽象路径是:/myweb/index.html
         * 如果浏览器输入的是http://localhost:8088/myweb/classTable.html
         * 则抽象路径是:/myweb/classTable.html
         */
        String path = request.getRequestURI();
        System.out.println("本次请求路径:" + path);
        //判断请求是否为请求某个业务
        HandlerMapping.MethodMapping methodMapping = HandlerMapping.getMethod(path);
        if (methodMapping != null) {//如果返回的内容不为null,说明当前的请求是一个业务
            //获取对应的业务类对象
            Object controller = methodMapping.getController();
            //获取对应的业务方法
            Method method = methodMapping.getMethod();
            try {
                method.invoke(controller, request,response);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        }
        //从static目录下,寻找是否有抽象路径下的文件
        File file = new File(staticDir, path);
        //如果抽象路径对应的是存在的文件,那么file就是文件
        if (file.isFile()) {
            //默认发送状态行就是HTTP/1.1 200 OK
            response.setContentFile(file);
        } else {//如果抽象路径对应的是不存在的文件,或者抽象路径没写,file就是一个目录
            //HTTP协议规定,访问资源不存在时,状态码是404,描述短语是NotFound
            response.setStatusCode(404);
            response.setStatusReason("NotFound");
            //由于资源不存在,需要返回给浏览器404页面
            file = new File(staticDir, "root/404.html");
            response.setContentFile(file);
        }
    }
}
